\myparagraph{GCC 4.4.1}

\lstinputlisting[caption=GCC 4.4.1,style=customasmx86]{patterns/12_FPU/3_comparison/x86/GCC_RU.asm}

\myindex{x86!\Instructions!FUCOMPP}
\FUCOMPP~--- это почти то же что и \FCOM, только выкидывает из стека оба значения после сравнения, 
а также несколько иначе реагирует на \q{не-числа}.

\myindex{Не-числа (NaNs)}
Немного о \IT{не-числах}.

\newcommand{\NANFN}{\footnote{\href{http://go.yurichev.com/17129}{ru.wikipedia.org/wiki/NaN}}}

FPU умеет работать со специальными переменными, которые числами не являются и называются \q{не числа} или 
\gls{NaN}\NANFN. 
Это бесконечность, результат деления на ноль, и так далее. Нечисла бывают \q{тихие} и \q{сигнализирующие}. 
С первыми можно продолжать работать и далее, а вот если вы попытаетесь совершить какую-то операцию 
с сигнализирующим нечислом, то сработает исключение.

\myindex{x86!\Instructions!FCOM}
\myindex{x86!\Instructions!FUCOM}
Так вот, \FCOM вызовет исключение если любой из операндов какое-либо нечисло.
\FUCOM же вызовет исключение только если один из операндов именно \q{сигнализирующее нечисло}.

\myindex{x86!\Instructions!SAHF}
\label{SAHF}
Далее мы видим \SAHF (\IT{Store AH into Flags})~--- это довольно редкая инструкция в коде, не использующим FPU. 
8 бит из \AH перекладываются в младшие 8 бит регистра статуса процессора в таком порядке:

\input{SAHF_LAHF}

\myindex{x86!\Instructions!FNSTSW}
Вспомним, что \FNSTSW перегружает интересующие нас биты \CThreeBits в \AH, 
и соответственно они будут в позициях 6, 2, 0 в регистре \AH:

\input{C3_in_AH}

Иными словами, пара инструкций \INS{fnstsw  ax / sahf} перекладывает биты \CThreeBits в флаги \ZF, \PF, \CF.

Теперь снова вспомним, какие значения бит \CThreeBits будут при каких результатах сравнения:

\begin{itemize}
\item Если $a$ больше $b$ в нашем случае, то биты \CThreeBits должны быть выставлены так: 0, 0, 0.
\item Если $a$ меньше $b$, то биты будут выставлены так: 0, 0, 1.
\item Если $a=b$, то так: 1, 0, 0.
\end{itemize}
% TODO: table?

Иными словами, после трех инструкций \FUCOMPP/\FNSTSW/\SAHF возможны такие состояния флагов:

\begin{itemize}
\item Если $a>b$ в нашем случае, то флаги будут выставлены так: \GTT{ZF=0, PF=0, CF=0}.
\item Если $a<b$, то флаги будут выставлены так: \GTT{ZF=0, PF=0, CF=1}.
\item Если $a=b$, то так: \GTT{ZF=1, PF=0, CF=0}.
\end{itemize}
% TODO: table?

\myindex{x86!\Instructions!SETcc}
\myindex{x86!\Instructions!JNBE}
Инструкция \SETNBE выставит в \AL единицу или ноль в зависимости от флагов и условий. 
Это почти аналог \JNBE, за тем лишь исключением, что \SETcc
\footnote{\IT{cc} это \IT{condition code}}
выставляет 1 или 0 в \AL, а \Jcc делает переход или нет. 
\SETNBE запишет 1 только если \GTT{CF=0} и \GTT{ZF=0}. Если это не так, то запишет 0 в \AL.

\CF будет 0 и \ZF будет 0 одновременно только в одном случае: если $a>b$.

Тогда в \AL будет записана 1, последующий условный переход \JZ выполнен не будет 
и функция вернет~\GTT{\_a}. 
В остальных случаях, функция вернет~\GTT{\_b}.
